package com.navinfo.platform.dataanalysis.service.impl;

import com.navinfo.platform.common.service.ICommonService;
import com.navinfo.platform.common.utils.StatisticsDef;
import com.navinfo.platform.dataanalysis.dto.*;
import com.navinfo.platform.dataanalysis.service.IStatisticsWeekOrMonthService;
import org.apache.commons.lang3.StringUtils;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.function.PairFlatMapFunction;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;
import scala.Tuple2;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 单车辆周或月统计信息
 *
 * @author wangshuai
 * @create 2018/11/27
 **/
public enum StatisticsWeekOrMonthService implements IStatisticsWeekOrMonthService {
    /**
     *
     */
    INSTANCE;

    /**
     * 将按天统计数据转换成JavaPairRDD<Long, List<VehicleBaseStatisticsDay>>
     *
     * @param dataSet   数据集合
     * @param configMap 配置文件信息
     * @return JavaPairRDD
     */
    @Override
    public JavaPairRDD<Long, List<VehicleBaseStatisticsDay>> convert(Dataset<Row> dataSet, Map<String, String> configMap, SparkSession spark) {
        return dataSet.toJavaRDD().mapToPair(new PairFunction<Row, Long, VehicleBaseStatisticsDay>() {
            @Override
            public Tuple2<Long, VehicleBaseStatisticsDay> call(Row row) throws Exception {
                VehicleBaseStatisticsDay statisticsDay = VehicleBaseStatisticsDay.parseObj(row);
                return new Tuple2<>(statisticsDay.getTid(),statisticsDay);
            }
        }).groupByKey().mapPartitionsToPair(new PairFlatMapFunction<Iterator<Tuple2<Long, Iterable<VehicleBaseStatisticsDay>>>, Long, List<VehicleBaseStatisticsDay>>() {
            @Override
            public Iterator<Tuple2<Long, List<VehicleBaseStatisticsDay>>> call(Iterator<Tuple2<Long, Iterable<VehicleBaseStatisticsDay>>> tuple2Iterator) throws Exception {
                return new Iterator<Tuple2<Long, List<VehicleBaseStatisticsDay>>>() {
                    @Override
                    public boolean hasNext() {
                        return tuple2Iterator.hasNext();
                    }

                    @Override
                    public Tuple2<Long, List<VehicleBaseStatisticsDay>> next() {
                        List<VehicleBaseStatisticsDay> list = new ArrayList<>();
                        Tuple2<Long, Iterable<VehicleBaseStatisticsDay>> tuple2 = tuple2Iterator.next();
                        Iterator<VehicleBaseStatisticsDay> iter = tuple2._2.iterator();
                        while (iter.hasNext()) {
                            VehicleBaseStatisticsDay statisticsDay = iter.next();
                                list.add(statisticsDay);
                        }
                        return new Tuple2<>(tuple2._1,list);
                    }
                };
            }
        });
    }

    /**
     * 根据天统计结果计算周或月统计结果的方法
     *
     * @param javaPairRDD 转换好的rdd
     * @param configMap   配置文件
     * @param spark       spark
     * @return 周或月统计rdd
     */
    @Override
    public JavaPairRDD<Long, VehicleBaseStatisticsWeekOrMonth> handle(JavaPairRDD<Long, List<VehicleBaseStatisticsDay>> javaPairRDD, Map<String, String> configMap, SparkSession spark) {
        String type = configMap.get(ICommonService.PARTITION_NUM_VALUE);
        //计算求和的指标
        JavaPairRDD<Long, VehicleBaseStatisticsWeekOrMonth> afterSumRDD = javaPairRDD.mapToPair(new PairFunction<Tuple2<Long, List<VehicleBaseStatisticsDay>>, Long, VehicleBaseStatisticsWeekOrMonth>() {
            @Override
            public Tuple2<Long, VehicleBaseStatisticsWeekOrMonth> call(Tuple2<Long, List<VehicleBaseStatisticsDay>> longListTuple2) throws Exception {
                List<VehicleBaseStatisticsDay> list = longListTuple2._2;
                VehicleBaseStatisticsWeekOrMonth weekOrMonth = new VehicleBaseStatisticsWeekOrMonth();
                for (int i = 0; i < list.size(); i++) {
                    VehicleBaseStatisticsDay statisticsDay = list.get(i);
                    if (i == 0) {
                        weekOrMonth.setUid(statisticsDay.getUid());
                        weekOrMonth.setTid(statisticsDay.getTid());
                        weekOrMonth.setDay(statisticsDay.getDay());
                    }
                    getSumResult(weekOrMonth, statisticsDay);
                }
                return new Tuple2<>(longListTuple2._1, weekOrMonth);
            }
        });
        JavaPairRDD<Long, VehicleBaseStatisticsWeekOrMonth> returnRDD = null;
        //根據參數判斷是計算周還是月
        returnRDD = afterSumRDD.mapToPair(new PairFunction<Tuple2<Long, VehicleBaseStatisticsWeekOrMonth>, Long, VehicleBaseStatisticsWeekOrMonth>() {
            @Override
            public Tuple2<Long, VehicleBaseStatisticsWeekOrMonth> call(Tuple2<Long, VehicleBaseStatisticsWeekOrMonth> longVehicleBaseStatisticsWeekOrMonthTuple2) throws Exception {
                VehicleBaseStatisticsWeekOrMonth weekOrMonth = null;
                if (StatisticsDef.WEEK.equals(type)) {
                    weekOrMonth = calculateWeek(longVehicleBaseStatisticsWeekOrMonthTuple2._2);
                } else if (StatisticsDef.MONTH.equals(type)) {
                    weekOrMonth = calculateMonth(longVehicleBaseStatisticsWeekOrMonthTuple2._2);
                }
                return new Tuple2<>(longVehicleBaseStatisticsWeekOrMonthTuple2._1, weekOrMonth);
            }
        });
        return returnRDD;
    }

    /**
     * 天统计累加成周或月统计
     *
     * @param weekOrMonth   周或月实体
     * @param statisticsDay 天统计实体
     */
    private static void getSumResult(VehicleBaseStatisticsWeekOrMonth weekOrMonth, VehicleBaseStatisticsDay statisticsDay) {
        weekOrMonth.setMileage(Optional.ofNullable(weekOrMonth.getMileage()).orElse(0) + Optional.ofNullable(statisticsDay.getMileage()).orElse(0));
        weekOrMonth.setFuelConsumption(Optional.ofNullable(weekOrMonth.getFuelConsumption()).orElse(0) + Optional.ofNullable(statisticsDay.getFuelConsumption()).orElse(0));
        //百公里平均油耗
        if (weekOrMonth.getMileage() > 0) {
            weekOrMonth.setAvgFuelConsumption(persist(((weekOrMonth.getFuelConsumption() / 1000.0) / (weekOrMonth.getMileage() / 1000.0)) * 100, 2));

        }
        weekOrMonth.setWorkDuration(Optional.ofNullable(weekOrMonth.getWorkDuration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkDuration()).orElse(0));
        weekOrMonth.setIdleDuration(Optional.ofNullable(weekOrMonth.getIdleDuration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleDuration()).orElse(0));
        weekOrMonth.setSpeed10Duration(Optional.ofNullable(weekOrMonth.getSpeed10Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed10Duration()).orElse(0));
        weekOrMonth.setSpeed20Duration(Optional.ofNullable(weekOrMonth.getSpeed20Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed20Duration()).orElse(0));
        weekOrMonth.setSpeed30Duration(Optional.ofNullable(weekOrMonth.getSpeed30Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed30Duration()).orElse(0));
        weekOrMonth.setSpeed40Duration(Optional.ofNullable(weekOrMonth.getSpeed40Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed40Duration()).orElse(0));
        weekOrMonth.setSpeed50Duration(Optional.ofNullable(weekOrMonth.getSpeed50Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed50Duration()).orElse(0));
        weekOrMonth.setSpeed60Duration(Optional.ofNullable(weekOrMonth.getSpeed60Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed60Duration()).orElse(0));
        weekOrMonth.setSpeed70Duration(Optional.ofNullable(weekOrMonth.getSpeed70Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed70Duration()).orElse(0));
        weekOrMonth.setSpeed80Duration(Optional.ofNullable(weekOrMonth.getSpeed80Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed80Duration()).orElse(0));
        weekOrMonth.setSpeed90Duration(Optional.ofNullable(weekOrMonth.getSpeed90Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed90Duration()).orElse(0));
        weekOrMonth.setSpeed100Duration(Optional.ofNullable(weekOrMonth.getSpeed100Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed100Duration()).orElse(0));
        weekOrMonth.setSpeed110Duration(Optional.ofNullable(weekOrMonth.getSpeed110Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed110Duration()).orElse(0));
        weekOrMonth.setSpeed120Duration(Optional.ofNullable(weekOrMonth.getSpeed120Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeed120Duration()).orElse(0));
        weekOrMonth.setSpeedOver120Duration(Optional.ofNullable(weekOrMonth.getSpeedOver120Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getSpeedOver120Duration()).orElse(0));
        //平均速度，里程/时长，单位：KM/H
        if (weekOrMonth.getWorkDuration() > 0) {
            weekOrMonth.setAvgSpeed(doubleFormatInt((weekOrMonth.getMileage() / 1000.0) / (weekOrMonth.getWorkDuration() / 3600.0)));
        }
        weekOrMonth.setMaxSpeed(maxAndMinDeal(weekOrMonth.getMaxSpeed(), statisticsDay.getMaxSpeed(), 0));
        weekOrMonth.setMaxUsefulSpeed(maxAndMinDeal(weekOrMonth.getMaxUsefulSpeed(), statisticsDay.getMaxUsefulSpeed(), 0));
        weekOrMonth.setMinUsefulSpeed(maxAndMinDeal(weekOrMonth.getMinUsefulSpeed(), statisticsDay.getMinUsefulSpeed(), 1));
        weekOrMonth.setWorkWaterTemp50Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp50Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp50Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp70Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp70Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp70Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp80Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp80Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp80Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp85Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp85Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp85Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp90Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp90Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp90Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp95Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp95Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp95Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp100Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp100Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp100Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp105Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp105Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp105Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp110Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp110Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp110Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp115Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp115Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp115Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp120Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp120Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp120Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp125Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp125Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp125Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp130Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp130Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp130Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp135Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp135Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp135Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp140Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp140Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp140Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp145Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp145Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp145Duration()).orElse(0));
        weekOrMonth.setWorkWaterTemp150Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTemp150Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTemp150Duration()).orElse(0));
        weekOrMonth.setWorkWaterTempOver150Duration(Optional.ofNullable(weekOrMonth.getWorkWaterTempOver150Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTempOver150Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp50Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp50Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp50Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp70Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp70Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp70Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp80Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp80Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp80Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp85Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp85Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp85Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp90Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp90Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp90Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp95Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp95Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp95Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp100Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp100Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp100Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp105Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp105Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp105Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp110Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp110Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp110Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp115Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp115Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp115Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp120Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp120Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp120Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp125Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp125Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp125Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp130Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp130Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp130Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp135Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp135Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp135Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp140Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp140Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp140Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp145Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp145Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp145Duration()).orElse(0));
        weekOrMonth.setIdleWaterTemp150Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTemp150Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTemp150Duration()).orElse(0));
        weekOrMonth.setIdleWaterTempOver150Duration(Optional.ofNullable(weekOrMonth.getIdleWaterTempOver150Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTempOver150Duration()).orElse(0));
        weekOrMonth.setMaxWorkWaterTemp(maxAndMinDeal(weekOrMonth.getMaxWorkWaterTemp(), statisticsDay.getMaxWorkWaterTemp(), 0));
        weekOrMonth.setMinWorkWaterTemp(maxAndMinDeal(weekOrMonth.getMinWorkWaterTemp(), statisticsDay.getMinWorkWaterTemp(), 1));
        weekOrMonth.setWorkWaterTempSum(Optional.ofNullable(weekOrMonth.getWorkWaterTempSum()).orElse(0L) + Optional.ofNullable(statisticsDay.getWorkWaterTempSum()).orElse(0L));
        weekOrMonth.setWorkWaterTempCount(Optional.ofNullable(weekOrMonth.getWorkWaterTempCount()).orElse(0) + Optional.ofNullable(statisticsDay.getWorkWaterTempCount()).orElse(0));
        if (weekOrMonth.getWorkWaterTempCount() > 0) {
            weekOrMonth.setAvgWorkWaterTemp(doubleFormatInt((weekOrMonth.getWorkWaterTempSum() + 0.0d) / weekOrMonth.getWorkWaterTempCount()));
        }
        weekOrMonth.setMaxIdleWaterTemp(maxAndMinDeal(weekOrMonth.getMaxIdleWaterTemp(), statisticsDay.getMaxIdleWaterTemp(), 0));
        weekOrMonth.setMinIdleWaterTemp(maxAndMinDeal(weekOrMonth.getMinIdleWaterTemp(), statisticsDay.getMinIdleWaterTemp(), 1));
        weekOrMonth.setIdleWaterTempSum(Optional.ofNullable(weekOrMonth.getIdleWaterTempSum()).orElse(0L) + Optional.ofNullable(statisticsDay.getIdleWaterTempSum()).orElse(0L));
        weekOrMonth.setIdleWaterTempCount(Optional.ofNullable(weekOrMonth.getIdleWaterTempCount()).orElse(0) + Optional.ofNullable(statisticsDay.getIdleWaterTempCount()).orElse(0));
        if (weekOrMonth.getIdleWaterTempCount() > 0) {
            weekOrMonth.setAvgIdleWaterTemp(doubleFormatInt((weekOrMonth.getIdleWaterTempSum() + 0.0d) / weekOrMonth.getIdleWaterTempCount()));
        }
        weekOrMonth.setGasOpenPercent0Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent0Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent0Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent10Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent10Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent10Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent20Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent20Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent20Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent30Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent30Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent30Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent40Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent40Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent40Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent50Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent50Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent50Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent60Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent60Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent60Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent70Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent70Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent70Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent80Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent80Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent80Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent90Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent90Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent90Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent99Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent99Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent99Duration()).orElse(0));
        weekOrMonth.setGasOpenPercent100Duration(Optional.ofNullable(weekOrMonth.getGasOpenPercent100Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercent100Duration()).orElse(0));
        weekOrMonth.setGasOpenPercentSum(Optional.ofNullable(weekOrMonth.getGasOpenPercentSum()).orElse(0L) + Optional.ofNullable(statisticsDay.getGasOpenPercentSum()).orElse(0L));
        weekOrMonth.setGasOpenPercentCount(Optional.ofNullable(weekOrMonth.getGasOpenPercentCount()).orElse(0) + Optional.ofNullable(statisticsDay.getGasOpenPercentCount()).orElse(0));
        if (weekOrMonth.getGasOpenPercentCount() > 0) {
            weekOrMonth.setAvgGasOpenPercent(doubleFormatInt((weekOrMonth.getGasOpenPercentSum() + 0.0d) / weekOrMonth.getGasOpenPercentCount()));
        }
        weekOrMonth.setTorque0Duration(Optional.ofNullable(weekOrMonth.getTorque0Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque0Duration()).orElse(0));
        weekOrMonth.setTorque10Duration(Optional.ofNullable(weekOrMonth.getTorque10Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque10Duration()).orElse(0));
        weekOrMonth.setTorque20Duration(Optional.ofNullable(weekOrMonth.getTorque20Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque20Duration()).orElse(0));
        weekOrMonth.setTorque30Duration(Optional.ofNullable(weekOrMonth.getTorque30Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque30Duration()).orElse(0));
        weekOrMonth.setTorque40Duration(Optional.ofNullable(weekOrMonth.getTorque40Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque40Duration()).orElse(0));
        weekOrMonth.setTorque50Duration(Optional.ofNullable(weekOrMonth.getTorque50Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque50Duration()).orElse(0));
        weekOrMonth.setTorque60Duration(Optional.ofNullable(weekOrMonth.getTorque60Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque60Duration()).orElse(0));
        weekOrMonth.setTorque70Duration(Optional.ofNullable(weekOrMonth.getTorque70Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque70Duration()).orElse(0));
        weekOrMonth.setTorque80Duration(Optional.ofNullable(weekOrMonth.getTorque80Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque80Duration()).orElse(0));
        weekOrMonth.setTorque90Duration(Optional.ofNullable(weekOrMonth.getTorque90Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque90Duration()).orElse(0));
        weekOrMonth.setTorque99Duration(Optional.ofNullable(weekOrMonth.getTorque99Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque99Duration()).orElse(0));
        weekOrMonth.setTorque100Duration(Optional.ofNullable(weekOrMonth.getTorque100Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getTorque100Duration()).orElse(0));
        weekOrMonth.setMaxTorque(maxAndMinDeal(weekOrMonth.getMaxTorque(), statisticsDay.getMaxTorque(), 0));
        weekOrMonth.setMinTorque(maxAndMinDeal(weekOrMonth.getMinTorque(), statisticsDay.getMinTorque(), 1));
        weekOrMonth.setTorqueSum(Optional.ofNullable(weekOrMonth.getTorqueSum()).orElse(0L) + Optional.ofNullable(statisticsDay.getTorqueSum()).orElse(0L));
        weekOrMonth.setTorqueCount(Optional.ofNullable(weekOrMonth.getTorqueCount()).orElse(0) + Optional.ofNullable(statisticsDay.getTorqueCount()).orElse(0));
        if (weekOrMonth.getTorqueCount() > 0) {
            weekOrMonth.setAvgTorque(doubleFormatInt((weekOrMonth.getTorqueSum() + 0.0d) / weekOrMonth.getTorqueCount()));
        }
        weekOrMonth.setRpm650Duration(Optional.ofNullable(weekOrMonth.getRpm650Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getRpm650Duration()).orElse(0));
        weekOrMonth.setRpm800Duration(Optional.ofNullable(weekOrMonth.getRpm800Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getRpm800Duration()).orElse(0));
        weekOrMonth.setRpm1100Duration(Optional.ofNullable(weekOrMonth.getRpm1100Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getRpm1100Duration()).orElse(0));
        weekOrMonth.setRpm1400Duration(Optional.ofNullable(weekOrMonth.getRpm1400Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getRpm1400Duration()).orElse(0));
        weekOrMonth.setRpm1700Duration(Optional.ofNullable(weekOrMonth.getRpm1700Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getRpm1700Duration()).orElse(0));
        weekOrMonth.setRpm2000Duration(Optional.ofNullable(weekOrMonth.getRpm2000Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getRpm2000Duration()).orElse(0));
        weekOrMonth.setRpm2300Duration(Optional.ofNullable(weekOrMonth.getRpm2300Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getRpm2300Duration()).orElse(0));
        weekOrMonth.setRpm2600Duration(Optional.ofNullable(weekOrMonth.getRpm2600Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getRpm2600Duration()).orElse(0));
        weekOrMonth.setRpmOver2600Duration(Optional.ofNullable(weekOrMonth.getRpmOver2600Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getRpmOver2600Duration()).orElse(0));
        weekOrMonth.setEcoRpmDuration(Optional.ofNullable(weekOrMonth.getEcoRpmDuration()).orElse(0) + Optional.ofNullable(statisticsDay.getEcoRpmDuration()).orElse(0));
        weekOrMonth.setEcoRpmPercent(Optional.ofNullable(weekOrMonth.getEcoRpmPercent()).orElse(0) + Optional.ofNullable(statisticsDay.getEcoRpmPercent()).orElse(0));
        weekOrMonth.setNoIdleRpmSum(Optional.ofNullable(weekOrMonth.getNoIdleRpmSum()).orElse(0L) + Optional.ofNullable(statisticsDay.getNoIdleRpmSum()).orElse(0L));
        weekOrMonth.setNoIdleRpmCount(Optional.ofNullable(weekOrMonth.getNoIdleRpmCount()).orElse(0) + Optional.ofNullable(statisticsDay.getNoIdleRpmCount()).orElse(0));
        if (weekOrMonth.getNoIdleRpmCount() > 0) {
            weekOrMonth.setNoIdleAvgRpm(doubleFormatInt((weekOrMonth.getNoIdleRpmSum() + 0.0d) / weekOrMonth.getNoIdleRpmCount()));
        }
        weekOrMonth.setRpmSum(Optional.ofNullable(weekOrMonth.getRpmSum()).orElse(0L) + Optional.ofNullable(statisticsDay.getRpmSum()).orElse(0L));
        weekOrMonth.setRpmCount(Optional.ofNullable(weekOrMonth.getRpmCount()).orElse(0) + Optional.ofNullable(statisticsDay.getRpmCount()).orElse(0));
        if (weekOrMonth.getRpmCount() > 0) {
            weekOrMonth.setAvgRpm(doubleFormatInt((weekOrMonth.getRpmSum() + 0.0d) / weekOrMonth.getRpmCount()));
        }
        weekOrMonth.setMaxRpm(maxAndMinDeal(weekOrMonth.getMaxRpm(), statisticsDay.getMaxRpm(), 0));
        weekOrMonth.setMinRpm(maxAndMinDeal(weekOrMonth.getMinRpm(), statisticsDay.getMinRpm(), 1));
        weekOrMonth.setIat50Duration(Optional.ofNullable(weekOrMonth.getIat50Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat50Duration()).orElse(0));
        weekOrMonth.setIat70Duration(Optional.ofNullable(weekOrMonth.getIat70Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat70Duration()).orElse(0));
        weekOrMonth.setIat80Duration(Optional.ofNullable(weekOrMonth.getIat80Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat80Duration()).orElse(0));
        weekOrMonth.setIat85Duration(Optional.ofNullable(weekOrMonth.getIat85Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat85Duration()).orElse(0));
        weekOrMonth.setIat90Duration(Optional.ofNullable(weekOrMonth.getIat90Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat90Duration()).orElse(0));
        weekOrMonth.setIat95Duration(Optional.ofNullable(weekOrMonth.getIat95Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat95Duration()).orElse(0));
        weekOrMonth.setIat100Duration(Optional.ofNullable(weekOrMonth.getIat100Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat100Duration()).orElse(0));
        weekOrMonth.setIat105Duration(Optional.ofNullable(weekOrMonth.getIat105Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat105Duration()).orElse(0));
        weekOrMonth.setIat110Duration(Optional.ofNullable(weekOrMonth.getIat110Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat110Duration()).orElse(0));
        weekOrMonth.setIat115Duration(Optional.ofNullable(weekOrMonth.getIat115Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat115Duration()).orElse(0));
        weekOrMonth.setIat120Duration(Optional.ofNullable(weekOrMonth.getIat120Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat120Duration()).orElse(0));
        weekOrMonth.setIat125Duration(Optional.ofNullable(weekOrMonth.getIat125Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat125Duration()).orElse(0));
        weekOrMonth.setIat130Duration(Optional.ofNullable(weekOrMonth.getIat130Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat130Duration()).orElse(0));
        weekOrMonth.setIat135Duration(Optional.ofNullable(weekOrMonth.getIat135Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat135Duration()).orElse(0));
        weekOrMonth.setIat140Duration(Optional.ofNullable(weekOrMonth.getIat140Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat140Duration()).orElse(0));
        weekOrMonth.setIat145Duration(Optional.ofNullable(weekOrMonth.getIat145Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat145Duration()).orElse(0));
        weekOrMonth.setIat150Duration(Optional.ofNullable(weekOrMonth.getIat150Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIat150Duration()).orElse(0));
        weekOrMonth.setIatOver150Duration(Optional.ofNullable(weekOrMonth.getIatOver150Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIatOver150Duration()).orElse(0));
        weekOrMonth.setIatSum(Optional.ofNullable(weekOrMonth.getIatSum()).orElse(0L) + Optional.ofNullable(statisticsDay.getIatSum()).orElse(0L));
        weekOrMonth.setIatCount(Optional.ofNullable(weekOrMonth.getIatCount()).orElse(0) + Optional.ofNullable(statisticsDay.getIatCount()).orElse(0));
        if (weekOrMonth.getIatCount() > 0) {
            weekOrMonth.setAvgIat(doubleFormatInt((weekOrMonth.getIatSum() + 0.0d) / weekOrMonth.getIatCount()));
        }
        weekOrMonth.setMaxIat(maxAndMinDeal(weekOrMonth.getMaxIat(), statisticsDay.getMaxIat(), 0));
        weekOrMonth.setMinIat(maxAndMinDeal(weekOrMonth.getMinIat(), statisticsDay.getMinIat(), 1));
        weekOrMonth.setIp50Duration(Optional.ofNullable(weekOrMonth.getIp50Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp50Duration()).orElse(0));
        weekOrMonth.setIp60Duration(Optional.ofNullable(weekOrMonth.getIp60Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp60Duration()).orElse(0));
        weekOrMonth.setIp70Duration(Optional.ofNullable(weekOrMonth.getIp70Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp70Duration()).orElse(0));
        weekOrMonth.setIp80Duration(Optional.ofNullable(weekOrMonth.getIp80Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp80Duration()).orElse(0));
        weekOrMonth.setIp90Duration(Optional.ofNullable(weekOrMonth.getIp90Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp90Duration()).orElse(0));
        weekOrMonth.setIp100Duration(Optional.ofNullable(weekOrMonth.getIp100Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp100Duration()).orElse(0));
        weekOrMonth.setIp110Duration(Optional.ofNullable(weekOrMonth.getIp110Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp110Duration()).orElse(0));
        weekOrMonth.setIp120Duration(Optional.ofNullable(weekOrMonth.getIp120Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp120Duration()).orElse(0));
        weekOrMonth.setIp130Duration(Optional.ofNullable(weekOrMonth.getIp130Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp130Duration()).orElse(0));
        weekOrMonth.setIp140Duration(Optional.ofNullable(weekOrMonth.getIp140Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp140Duration()).orElse(0));
        weekOrMonth.setIp150Duration(Optional.ofNullable(weekOrMonth.getIp150Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIp150Duration()).orElse(0));
        weekOrMonth.setIpOver150Duration(Optional.ofNullable(weekOrMonth.getIpOver150Duration()).orElse(0) + Optional.ofNullable(statisticsDay.getIpOver150Duration()).orElse(0));
        weekOrMonth.setIpSum(Optional.ofNullable(weekOrMonth.getIpSum()).orElse(0L) + Optional.ofNullable(statisticsDay.getIpSum()).orElse(0L));
        weekOrMonth.setIpCount(Optional.ofNullable(weekOrMonth.getIpCount()).orElse(0) + Optional.ofNullable(statisticsDay.getIpCount()).orElse(0));
        if (weekOrMonth.getIpCount() > 0) {
            weekOrMonth.setAvgIp(doubleFormatInt((weekOrMonth.getIpSum() + 0.0d) / weekOrMonth.getIpCount()));
        }
        weekOrMonth.setMaxIp(maxAndMinDeal(weekOrMonth.getMaxIp(), statisticsDay.getMaxIp(), 0));
        weekOrMonth.setMinIp(maxAndMinDeal(weekOrMonth.getMinIp(), statisticsDay.getMinIp(), 1));

        HashSet<String> total = new HashSet<>();
        if (StringUtils.isNotEmpty(weekOrMonth.getCrossCities())) {
            String[] split = weekOrMonth.getCrossCities().split(",");
            total.addAll(Arrays.asList(split));
        }
        HashSet<String> add = new HashSet<>();
        if (StringUtils.isNotEmpty(statisticsDay.getCrossCities())) {
            String[] split = statisticsDay.getCrossCities().split(",");
            add.addAll(Arrays.asList(split));
        }
        total.addAll(add);
        if (total.size() > 0) {
            String crossCities = String.join(",", total);
            weekOrMonth.setCrossCities(crossCities);
        }
    }


    /**
     * 计算周信息
     *
     * @param vehicleBaseStatisticsWeekOrMonth 实体类
     * @return 周实体
     */
    private VehicleBaseStatisticsWeekOrMonth calculateWeek(VehicleBaseStatisticsWeekOrMonth vehicleBaseStatisticsWeekOrMonth) {
        //調整爲該周的週一
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date();
        try {
            date = sdf.parse(String.valueOf(vehicleBaseStatisticsWeekOrMonth.getDay()));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        vehicleBaseStatisticsWeekOrMonth.setDay(sdf.format(calendar.getTime()));
        vehicleBaseStatisticsWeekOrMonth.setAvgMileage(doubleFormatInt(vehicleBaseStatisticsWeekOrMonth.getMileage() / 7.0));
        vehicleBaseStatisticsWeekOrMonth.setAvgWorkDuration(doubleFormatInt(vehicleBaseStatisticsWeekOrMonth.getWorkDuration() / 7.0));
        vehicleBaseStatisticsWeekOrMonth.setAvgIdleDuration(doubleFormatInt(vehicleBaseStatisticsWeekOrMonth.getIdleDuration() / 7.0));
        return vehicleBaseStatisticsWeekOrMonth;
    }


    /**
     * 计算月度信息
     *
     * @param vehicleBaseStatisticsWeekOrMonth 实体类
     * @return 月实体
     */
    private VehicleBaseStatisticsWeekOrMonth calculateMonth(VehicleBaseStatisticsWeekOrMonth vehicleBaseStatisticsWeekOrMonth) {
        //調整爲該月的1號
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date();
        try {
            date = sdf.parse(String.valueOf(vehicleBaseStatisticsWeekOrMonth.getDay()));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int count = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        vehicleBaseStatisticsWeekOrMonth.setDay(sdf.format(calendar.getTime()));
        vehicleBaseStatisticsWeekOrMonth.setAvgMileage(doubleFormatInt((vehicleBaseStatisticsWeekOrMonth.getMileage() + 0.0) / count));
        vehicleBaseStatisticsWeekOrMonth.setAvgWorkDuration(doubleFormatInt((vehicleBaseStatisticsWeekOrMonth.getWorkDuration() + 0.0) / count));
        vehicleBaseStatisticsWeekOrMonth.setAvgIdleDuration(doubleFormatInt((vehicleBaseStatisticsWeekOrMonth.getIdleDuration() + 0.0) / count));
        return vehicleBaseStatisticsWeekOrMonth;
    }

    /**
     * 對比並選出最大或者最小值
     *
     * @param a    數甲
     * @param b    數乙
     * @param type 0：比大；1：比小
     * @return 最大或最小值
     */
    private static Integer maxAndMinDeal(Integer a, Integer b, int type) {
        if (a == null) {
            return b;
        } else if (b == null) {
            return a;
        } else {
            int weekOrMonth = Optional.ofNullable(a).orElse(0);
            int day = Optional.ofNullable(b).orElse(0);
            if (type == 0 && day > weekOrMonth) {
                return day;
            } else if (type == 1 && day < weekOrMonth) {
                return day;
            } else {
                return a;
            }
        }
    }

    /**
     * 保留n位小数
     *
     * @param f        小数
     * @param newScale 保留几位
     * @return 保留小数位后的浮点数
     */
    public static double persist(double f, int newScale) {
        BigDecimal bg = new BigDecimal(f);
        double f1 = bg.setScale(newScale, BigDecimal.ROUND_HALF_UP).doubleValue();
        return f1;
    }

    /**
     * 四舍五入转换成整数
     *
     * @param dou 输入的浮点数
     * @return 一个整数
     */
    public static int doubleFormatInt(Double dou) {
        //四舍五入转换成整数
        DecimalFormat df = new DecimalFormat("######0");
        return Integer.parseInt(df.format(dou));
    }
}
